package com.bitsfromspace.ubertorrent.tracker;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import com.bitsfromspace.ubertorrent.Sha1Hash;
import com.bitsfromspace.ubertorrent.bencoding.BValue;
import com.bitsfromspace.ubertorrent.utils.ByteUtils;

/**
 * HTTP Implementation of {@link TorrentRequest}.
 * @author: chris.oudeman
 * @since: Jan 6, 2011
 */
class TorrentHttpRequest implements TorrentRequest {




	private final String trackerUrl;
	private final Sha1Hash infoHash;
	private final Sha1Hash peerId;
	private final int port;
	private final long uploaded;
	private final long downloaded;
	private final long left;
	private final RequestEvent event;
	private final String ipAddress;
	private final String trackerId;

	protected TorrentHttpRequest(
			String trackerUrl,
			Sha1Hash infoHash,
			Sha1Hash peerId,
			int port,
			long uploaded,
			long downloaded,
			long left,
			RequestEvent event,
			String ipAddress,
			String trackerId) {

		this.trackerUrl = trackerUrl;
		this.infoHash = infoHash;
		this.peerId = peerId;
		this.port = port;
		this.uploaded = uploaded;
		this.downloaded = downloaded;
		this.left = left;
		this.event = event;
		this.ipAddress = ipAddress;
		this.trackerId = trackerId;
	}

	@Override
	public TorrentResponse execute(int timeoutInMillis) throws IOException {
		
		String encodedUrl = generateHttpGet();

		HttpURLConnection httpConnection =
				(HttpURLConnection) new URL(encodedUrl).openConnection();
		httpConnection.setConnectTimeout(timeoutInMillis);
		httpConnection.setReadTimeout(timeoutInMillis);

		String response = readResponse(httpConnection);
		
		return TorrentResponse.createFromHttpResponse(response);

	}


	/**
	 * Reads the complete http response, closes the http connection and returns the response as an UTF encoded string.
	 */
	private String readResponse(HttpURLConnection httpConnection)
																	throws IOException {

		if (httpConnection.getResponseCode() != 200){
			throw new IOException("HTTP " + httpConnection.getResponseCode()
					+ " " + httpConnection.getResponseMessage());
		}

		byte[] buffer = new byte[64 * 1024];
		int actualRead = -1;
		StringBuilder responseBuffer = new StringBuilder();
		InputStream in = null;
		try {
			in = httpConnection.getInputStream();
			while ((actualRead = in.read(buffer)) != -1) {
				responseBuffer.append(new String(
						buffer,
						0,
						actualRead,
						BValue.UTF8));
			}
		} finally {
			if (in != null) {
				in.close();
			}
			httpConnection.disconnect();
		}
		return responseBuffer.toString();
	}

	/**
	 * Generate HTTP get from this request's parameters.
	 */
	protected String generateHttpGet() {

		StringBuilder urlBuffer = new StringBuilder(trackerUrl).append("?");
		urlBuffer.append("info_hash=").append(
				ByteUtils.urlEncodeByteString(infoHash.getHash()));

		urlBuffer.append("&peer_id=").append(
				ByteUtils.urlEncodeByteString(peerId.getHash()));

		urlBuffer.append("&port=").append(port);
		urlBuffer.append("&uploaded=").append(uploaded);
		urlBuffer.append("&downloaded=").append(downloaded);
		urlBuffer.append("&left=").append(left);
		urlBuffer.append("&compact=1");
		urlBuffer.append("&ip=").append(ipAddress);

		if (event != RequestEvent.NONE) {
			urlBuffer.append("&event=").append(event.toString());
		}
		if (trackerId != null) {
			urlBuffer.append("&trackerId=").append(trackerId);
		}
		
		return urlBuffer.toString();

	}

	


}